package com.fosss.band.service.impl;

import com.fosss.band.constant.RedisKeyConstant;
import com.fosss.band.entity.User;
import com.fosss.band.entity.vo.LoginUserVo;
import com.fosss.band.entity.vo.RegisterUserVo;
import com.fosss.band.entity.vo.UserInfoVo;
import com.fosss.band.mapper.UserMapper;
import com.fosss.band.service.UserService;
import com.fosss.band.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.fosss.band.utils.ResultCodeEnum.*;

/**
 * @author: fosss
 * Date: 2023/12/28
 * Time: 17:36
 * Description:
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private SendMailUtil sendMailUtil;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 用户登录
     */
    @Override
    public Result login(LoginUserVo loginUser) {
        //非空判断
        if (loginUser == null || StringUtils.isEmpty(loginUser.getUsername()) || StringUtils.isEmpty(loginUser.getPassword())) {
            return Result.error().code(LOGIN_USER_ERROR.getCode()).message(LOGIN_USER_ERROR.getMessage());
        }
        //判断用户是否存在，由于用户输入的是用户名或邮箱，所以分别判断
        //1. 判断用户是否存在
        User user = userMapper.selectByUsername(loginUser.getUsername());
        //2. 判断邮箱是否存在
        User userByEmail = null;
        if (CheckEmailUtil.checkEmail(loginUser.getUsername())) {
            //输入的是邮箱
            userByEmail = userMapper.selectByEmail(loginUser.getUsername());
        }
        if (user == null && userByEmail == null) {
            //输入的既不是用户名也不是邮箱，说明用户不存在
            return Result.error().code(ACCOUNT_ERROR.getCode()).message(ACCOUNT_ERROR.getMessage());
        }
        //确定用户
        user = user == null ? userByEmail : user;
        //判断密码是否正确，密码经过md5加密
        if (!user.getPassword().equals(MD5.encrypt(loginUser.getPassword()))) {
            return Result.error().code(PASSWORD_ERROR.getCode()).message(PASSWORD_ERROR.getMessage());
        }
        //登录后存入线程
        ThreadLocalUtil.set(user);
        // 登录后将用户存入redis
        String key = RedisKeyConstant.KEY_USER_LOGIN + user.getId();
        redisTemplate.opsForValue().set(key, JsonUtil.getJSONString(user), RedisKeyConstant.KEY_USER_LOGIN_TIMEOUT,
                TimeUnit.SECONDS);
        //登录成功
        return Result.ok().data("token", user.getId());
    }

    /**
     * 发送验证码
     */
    @Override
    public Result sendCode(String email) {
        if (StringUtils.isEmpty(email) || !CheckEmailUtil.checkEmail(email)) {
            return Result.error().code(EMAIL_ERROR.getCode()).message(EMAIL_ERROR.getMessage());
        }
        //获取验证码
        String sixBitRandom = RandomUtil.getSixBitRandom();
        //存入缓存5分钟
        String key = RedisKeyConstant.KEY_EMAIL_CODE + email;
        redisTemplate.opsForValue().set(key, sixBitRandom, RedisKeyConstant.KEY_EMAIL_CODE_EXPIRE, TimeUnit.SECONDS);
        //发送邮件
        sendMailUtil.sendMail(email, sixBitRandom);
        return Result.ok();
    }

    /**
     * 注册
     */
    @Override
    public Result register(RegisterUserVo registerUser) {
        //健壮性判断
        if (registerUser == null || StringUtils.isEmpty(registerUser.getEmail()) || StringUtils.isEmpty(registerUser.getVerifyCode())
                || StringUtils.isEmpty(registerUser.getPassword()) || !CheckEmailUtil.checkEmail(registerUser.getEmail())) {
            return Result.error();
        }
        //判断验证码是否正确
        String key = RedisKeyConstant.KEY_EMAIL_CODE + registerUser.getEmail();
        String code = redisTemplate.opsForValue().get(key);
        //判断是否过期
        if (code == null)
            return Result.error().code(VERIFY_CODE_TIMEOUT.getCode()).message(VERIFY_CODE_TIMEOUT.getMessage());
        if (code.equals(registerUser.getVerifyCode())) {
            //验证码正确
            //删除缓存中的验证码
            redisTemplate.delete(key);
            //判断该邮箱是否被注册过
            User u = userMapper.selectByEmail(registerUser.getEmail());
            if (u != null) return Result.error().code(EMAIL_REPEAT.getCode()).message(EMAIL_REPEAT.getMessage());

            User user = new User();
            //生成默认不重复用户名
            user.setUsername(RandomUsernameUtil.generateRandomUsername());
            user.setEmail(registerUser.getEmail());
            user.setPassword(MD5.encrypt(registerUser.getPassword()));
            user.setCreateTime(new Date());
            //添加默认头像
            user.setAvatar("https://hhu-band-user-avatar.oss-cn-nanjing.aliyuncs.com/default.png?Expires=1703929130&OSSAccessKeyId=TMP.3KdfUBQQsPBESLGDwwNnMCcfWuCgFfW3PVzBJLa6nhgusyuG59tNQKeH8tJvZukSjFeB1qEANeu9K4jXxUoe5nyceYnMzt&Signature=%2BZ3JiTYldKwNzKDC41cRrxZRVbE%3D");
            //添加用户
            userMapper.insert(user);
            return Result.ok();
        }
        //验证码错误
        return Result.error().code(VERIFY_CODE_ERROR.getCode()).message(VERIFY_CODE_ERROR.getMessage());
    }

    /**
     * 找回密码
     */
    @Override
    public Result forgetPassword(RegisterUserVo registerUser) {
        //健壮性判断
        if (registerUser == null || StringUtils.isEmpty(registerUser.getEmail()) || StringUtils.isEmpty(registerUser.getVerifyCode())
                || StringUtils.isEmpty(registerUser.getPassword()) || !CheckEmailUtil.checkEmail(registerUser.getEmail())) {
            return Result.error();
        }
        //判断验证码是否正确
        String key = RedisKeyConstant.KEY_EMAIL_CODE + registerUser.getEmail();
        String code = redisTemplate.opsForValue().get(key);
        //判断是否过期
        if (code == null)
            return Result.error().code(VERIFY_CODE_TIMEOUT.getCode()).message(VERIFY_CODE_TIMEOUT.getMessage());
        if (code.equals(registerUser.getVerifyCode())) {
            //验证码正确
            //删除缓存中的验证码
            redisTemplate.delete(key);
            //判断该邮箱是否被注册过
            User u = userMapper.selectByEmail(registerUser.getEmail());
            if (u == null) return Result.error().code(ACCOUNT_ERROR.getCode()).message(ACCOUNT_ERROR.getMessage());
            //修改密码
            u.setPassword(MD5.encrypt(registerUser.getPassword()));
            userMapper.update(u);
            return Result.ok();
        }
        //验证码错误
        return Result.error().code(VERIFY_CODE_ERROR.getCode()).message(VERIFY_CODE_ERROR.getMessage());
    }

    /**
     * 获取用户信息
     */
    @Override
    public Result info(String token) {
        //从缓存查询用户
        String key = RedisKeyConstant.KEY_USER_LOGIN + token;
        String user = redisTemplate.opsForValue().get(key);
        if (user == null) return Result.error().code(LOGIN_TIMEOUT.getCode()).message(LOGIN_TIMEOUT.getMessage());
        //json转对象
        User u = (User) JsonUtil.getJSONObject(user, User.class);
        int roleCode = u.getRole();
        String[] role = RoleUtil.getRole(roleCode);
        return Result.ok()
                .data("name", u.getUsername())
                .data("email", u.getEmail())
                .data("roles", role)//用户角色必须是数据！！！！！！！！！！！！！！！！！！！！！！！！！
                .data("avatar", u.getAvatar())
                .data("gender", u.getGender())
                .data("age", u.getAge())
                .data("profession", u.getProfession())
                .data("education", u.getEducation());
    }

    /**
     * 用户登出
     */
    @Override
    public Result logout(String token) {
        //从线程删去
        ThreadLocalUtil.clear();
        String key = RedisKeyConstant.KEY_USER_LOGIN + token;
        redisTemplate.delete(key);
        return Result.ok();
    }

    /**
     * 修改个人信息
     */
    @Override
    public Result saveInfo(UserInfoVo userInfoVo) {
        //先根据用户id查询到用户信息  由于用户名和邮箱可能被修改，所以使用id查询
        if (userInfoVo == null || userInfoVo.getId() == null) return Result.error();
        User user = userMapper.selectById(userInfoVo.getId());
        if (user == null) return Result.error().code(ACCOUNT_ERROR.getCode()).message(ACCOUNT_ERROR.getMessage());
        //检查密码是否正确
        if (!user.getPassword().equals(MD5.encrypt(userInfoVo.getPassword())))
            return Result.error().code(PASSWORD_ERROR.getCode()).message(PASSWORD_ERROR.getMessage());
        //检查用户名、邮箱是否为空，是否重复
        if (!user.getUsername().equals(userInfoVo.getUsername())) {
            //用户名被修改，检查是否重复
            User u = userMapper.selectByUsername(userInfoVo.getUsername());
            if (u != null) return Result.error().code(USERNAME_REPEAT.getCode()).message(USERNAME_REPEAT.getMessage());
        }
        //邮箱修改单独抽取一个api
        //进行修改
        user.setAvatar(userInfoVo.getAvatar());
        user.setUsername(userInfoVo.getUsername());
        user.setGender(userInfoVo.getGender());
        user.setAge(userInfoVo.getAge());
        user.setProfession(userInfoVo.getProfession());
        user.setEducation(userInfoVo.getEducation());
        userMapper.update(user);
        //注意，更新缓存!!!!!!!!!
        String key = RedisKeyConstant.KEY_USER_LOGIN + user.getId();
        redisTemplate.opsForValue().set(key, JsonUtil.getJSONString(user));
        return Result.ok();
    }

    /**
     * 验证验证码是否正确，直接把用户信息改掉
     */
    @Override
    public Result emailCodeRight(String email, String code) {
        String key = RedisKeyConstant.KEY_EMAIL_CODE + email;
        String s = redisTemplate.opsForValue().get(key);
        if (s == null)
            return Result.error().code(VERIFY_CODE_TIMEOUT.getCode()).message(VERIFY_CODE_TIMEOUT.getMessage());
        if (!s.equals(code))
            return Result.error().code(VERIFY_CODE_ERROR.getCode()).message(VERIFY_CODE_ERROR.getMessage());
        //删除缓存中的验证码
        redisTemplate.delete(key);
        //修改
        User user = userMapper.selectByEmail(email);
        user.setEmail(email);
        userMapper.update(user);
        return Result.ok();
    }

    /**
     * 根据用户名获取用户信息
     */
    @Override
    public Result getByUsername(String username) {
        User user = userMapper.selectByUsername(username);
        return Result.ok().data("row", user);
    }


}














